package com.ruicar.afs.cloud.bizcommon.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.bizcommon.business.bean.FinanceCalculatorBean;
import com.ruicar.afs.cloud.bizcommon.business.bean.FinanceInfoBean;
import com.ruicar.afs.cloud.bizcommon.business.condition.ApplyTotalCondition;
import com.ruicar.afs.cloud.bizcommon.business.dto.CalculatorDTO;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinCostDetails;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinDiscountDetails;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinFinancingItems;
import com.ruicar.afs.cloud.bizcommon.business.mapper.ApplyCostDetailsMapper;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyCostDetailsService;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyDiscountDetailsService;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyFinancingItemsService;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyRentAdjustDetailsService;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.parameter.commom.enums.CostType;
import com.ruicar.afs.cloud.parameter.commom.enums.WhetherEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 融资费用
 * @author: sijun.yu
 * @date: 2020/5/16 11:41
 */
@Slf4j
@Service
@AllArgsConstructor
public class ApplyCostDetailsServiceImpl extends ServiceImpl<ApplyCostDetailsMapper, FinCostDetails> implements ApplyCostDetailsService {

    private ApplyDiscountDetailsService discountDetailsService;
    private ApplyFinancingItemsService financingItemsService;
    private ApplyRentAdjustDetailsService rentAdjustDetailsService;
    private UidGenerator uidGenerator;

    /**
     * 获取客户利率（月） 只舍不入，保留一位小数
     * @param loanTerm
     * @param firstRent
     * @param loanAmt
     * @return
     */
    public BigDecimal getMonthlyRate(Integer loanTerm,BigDecimal firstRent,BigDecimal loanAmt){

        BigDecimal term = new BigDecimal(loanTerm);
        return (firstRent.multiply(term).subtract(loanAmt)).multiply(new BigDecimal("1000")).divide(term.multiply(loanAmt),1,BigDecimal.ROUND_DOWN);
    }

    /**
     * 万元系数法，只舍不入，保留整数
     * @param firstRent
     * @param loanAmt
     * @return
     */
    public BigDecimal getMyriadCoefficient(BigDecimal firstRent,BigDecimal loanAmt){

        return new BigDecimal("10000").multiply(firstRent).divide(loanAmt,0,BigDecimal.ROUND_DOWN);
    }

    /**
     * 获取融资信息合计信息
     *
     * @param vo
     * @param condition
     */
    public void getFinanceCostTotal(FinanceCalculatorBean vo, CalculatorDTO condition) {

        List<FinCostDetails> list = this.baseMapper.selectList(Wrappers.<FinCostDetails>query().lambda()
                .eq(FinCostDetails::getApplyNo, condition.getApplyNo())
                .eq(ObjectUtil.isNotNull(condition.getCarId()),FinCostDetails::getCarId, condition.getCarId()));
        if (list == null || list.size() == 0) {
            return;
        }
        // 汇总金额
        BigDecimal totalContractAmt = BigDecimal.ZERO;
        BigDecimal totalLoanAmt = BigDecimal.ZERO;
        BigDecimal totalFirstAmt = BigDecimal.ZERO;
        BigDecimal totalDiscountAmt = BigDecimal.ZERO;
        BigDecimal totalInterest = BigDecimal.ZERO;
        BigDecimal totalRent = BigDecimal.ZERO;
        BigDecimal totalTailAmt = BigDecimal.ZERO;
        for (FinCostDetails costDetails : list) {
            totalContractAmt = totalContractAmt.add(costDetails.getContractAmt() == null ? BigDecimal.ZERO : costDetails.getContractAmt());
            totalLoanAmt = totalLoanAmt.add(costDetails.getLoanAmt() == null ? BigDecimal.ZERO : costDetails.getLoanAmt());
            totalFirstAmt = totalFirstAmt.add(costDetails.getDownPayAmt() == null ? BigDecimal.ZERO : costDetails.getDownPayAmt());
            totalDiscountAmt = totalDiscountAmt.add(costDetails.getDiscountAmt() == null ? BigDecimal.ZERO : costDetails.getDiscountAmt());
            totalRent = totalRent.add(costDetails.getTotalRent() == null ? BigDecimal.ZERO : costDetails.getTotalRent());
            totalInterest = totalInterest.add(costDetails.getTotalInterest() == null ? BigDecimal.ZERO : costDetails.getTotalInterest());
            totalTailAmt = totalTailAmt.add(costDetails.getTailPayAmt() == null ? BigDecimal.ZERO : costDetails.getTailPayAmt());
        }
        vo.setTotalContractAmt(totalContractAmt);
        vo.setTotalLoanAmt(totalLoanAmt);
        vo.setTotalFirstAmt(totalFirstAmt);
        vo.setTotalDiscountAmt(totalDiscountAmt);
        vo.setTotalInterest(totalInterest);
        vo.setTotalRent(totalRent);
        vo.setTotalTailAmt(totalTailAmt);
    }

    /**
     * 保存或更新融资明细
     * @param applyNo
     * @param condition
     * @return
     */
    public FinCostDetails saveOrUpdateCostDetails(String applyNo, CalculatorDTO condition){

        FinCostDetails costDetails = this.getApplyCostDetails(applyNo,condition.getCostType());
        if(costDetails != null){
            this.upateApplyCostDetails(costDetails,condition);
        }else{
            costDetails = this.saveApplyCostDetails(applyNo,condition);
        }
        return costDetails;
    }

    /**
     * 保存融资明细
     *
     * @param condition
     */
    public FinCostDetails saveApplyCostDetails(String applyNo, CalculatorDTO condition) {

        // 客户利率非空判断
        Assert.isTrue(condition.getCustRate()!=null,"客户利率为空，请输入正确产品期数");
        FinCostDetails costDetails = new FinCostDetails();
        costDetails.setId(uidGenerator.getUID());
        costDetails.setApplyNo(applyNo);
        costDetails.setCarId(condition.getCarId());
        costDetails.setCostType(condition.getCostType());
        costDetails.setAlgorithmType(condition.getAlgorithmType());
        costDetails.setProductId(condition.getProductId());
        costDetails.setProductName(condition.getProductName());
        costDetails.setContractAmt(condition.getContractAmt());
        costDetails.setLoanTerm(condition.getLoanTerm());
        costDetails.setCustRate(condition.getCustRate());
        costDetails.setSettleRate(condition.getSettleRate());
        costDetails.setDownPayScale(condition.getDownPayScale());
        costDetails.setDownPayAmt(condition.getDownPayAmt());
        costDetails.setIsTail(condition.getIsTail());
        costDetails.setTailPayScale(condition.getTailPayScale());
        costDetails.setTailPayAmt(condition.getTailPayAmt());
        costDetails.setDiscountType(condition.getDiscountType());
        costDetails.setDiscountAmt(condition.getDiscountAmt());
        costDetails.setMaxDiscountAmt(condition.getMaxDiscountAmt());
        costDetails.setLoanAmt(condition.getLoanAmt());
        costDetails.setTotalInterest(condition.getTotalInterest());
        costDetails.setTotalRent(condition.getTotalRent());
        costDetails.setMonthPayAmt(condition.getMonthPayAmt());
        costDetails.setIsSubProduct(condition.getIsSubProduct());
        costDetails.setAddAmt(condition.getAddAmt());
        if(ObjectUtil.isNotNull(condition.getAddPointValue())){
            costDetails.setBasicPoint(condition.getAddPointValue());
        }
        costDetails.setRepaymentMethod(condition.getRepaymentMethod());
        this.baseMapper.insert(costDetails);

        return costDetails;
    }

    /**
     * 更新费用信息
     *
     * @param condition
     */
    public void upateApplyCostDetails(FinCostDetails costDetails, CalculatorDTO condition) {

        // 客户利率非空判断
        Assert.isTrue(condition.getCustRate()!=null,"客户利率为空，请输入正确产品期数");
        costDetails.setApplyNo(condition.getApplyNo());
        costDetails.setCarId(condition.getCarId());
        costDetails.setCostType(condition.getCostType());
        costDetails.setAlgorithmType(condition.getAlgorithmType());
        costDetails.setProductId(condition.getProductId());
        costDetails.setProductName(condition.getProductName());
        costDetails.setContractAmt(condition.getContractAmt());
        costDetails.setLoanTerm(condition.getLoanTerm());
        costDetails.setCustRate(condition.getCustRate());
        costDetails.setSettleRate(condition.getSettleRate());
        costDetails.setDownPayScale(condition.getDownPayScale());
        costDetails.setDownPayAmt(condition.getDownPayAmt());
        costDetails.setIsTail(condition.getIsTail());
        if(WhetherEnum.YES.getIndex().equals(condition.getIsTail())){
            costDetails.setTailPayScale(condition.getTailPayScale());
            costDetails.setTailPayAmt(condition.getTailPayAmt());
        }else{
            costDetails.setTailPayScale(BigDecimal.ZERO);
            costDetails.setTailPayAmt(BigDecimal.ZERO);
        }
        costDetails.setDiscountType(condition.getDiscountType());
        costDetails.setDiscountAmt(condition.getDiscountAmt());
        costDetails.setMaxDiscountAmt(condition.getMaxDiscountAmt());
        costDetails.setLoanAmt(condition.getLoanAmt());
        costDetails.setTotalRent(condition.getTotalRent());
        costDetails.setTotalInterest(condition.getTotalInterest());
        costDetails.setMonthPayAmt(condition.getMonthPayAmt());
        if(StringUtil.isNotBlank(condition.getIsSubProduct())){
            costDetails.setIsSubProduct(condition.getIsSubProduct());
            costDetails.setAddAmt(condition.getAddAmt());
        }else{
            costDetails.setIsSubProduct("");
            costDetails.setAddAmt(BigDecimal.ZERO);
        }
        if(ObjectUtil.isNotNull(condition.getAddPointValue())){
            costDetails.setBasicPoint(condition.getAddPointValue());
        }
        costDetails.setRepaymentMethod(condition.getRepaymentMethod());
        this.baseMapper.updateById(costDetails);
    }

    /**
     * 通过申请编号获取列表
     * @param applyNo
     * @return
     */
    public List<FinCostDetails> getCostDetailsList(String applyNo){

        return this.baseMapper.selectList(Wrappers.<FinCostDetails>query().lambda().eq(FinCostDetails::getApplyNo, applyNo));
    }

    /**
     * 通过申请编号和费用类型查询
     *
     * @param applyNo
     * @param costType
     * @return
     */
    public FinCostDetails getApplyCostDetails(String applyNo, String costType) {

        FinCostDetails costDetails = this.baseMapper.selectOne(Wrappers.<FinCostDetails>query().lambda()
                .eq(FinCostDetails::getApplyNo, applyNo)
                .eq(FinCostDetails::getCostType, costType));
        return costDetails;
    }

    /**
     * 通过申请编号、费用类型、车辆ID查询
     *
     * @param applyNo
     * @param carId
     * @param costType
     * @return
     */
    public FinCostDetails getApplyCostDetails(String applyNo, Long carId, String costType) {

        FinCostDetails costDetails = this.baseMapper.selectOne(Wrappers.<FinCostDetails>query().lambda()
                .eq(FinCostDetails::getApplyNo, applyNo)
                .eq(ObjectUtil.isNotNull(carId),FinCostDetails::getCarId, carId)
                .eq(FinCostDetails::getCostType, costType));
        return costDetails;
    }

    /**
     * 获取车辆产品信息
     *
     * @param applyNo
     * @param carId
     * @param costType
     * @return
     */
    public FinanceInfoBean getCarProductInfo(String applyNo, Long carId, String costType) {

        FinanceInfoBean vo = null;
        // 车款费用信息
        FinCostDetails costDetails = this.getApplyCostDetails(applyNo, carId, costType);
        if (costDetails != null) {
            vo = new FinanceInfoBean();
            if("equalrental".equals(costDetails.getAlgorithmType())){
                BigDecimal monthlyRate = this.getMonthlyRate(costDetails.getLoanTerm(),costDetails.getMonthPayAmt(),costDetails.getLoanAmt());
                costDetails.setMonthlyRate(monthlyRate);
                BigDecimal myriadCoefficient = this.getMyriadCoefficient(costDetails.getMonthPayAmt(),costDetails.getLoanAmt());
                costDetails.setMyriadCoefficient(myriadCoefficient);
            }
            vo.setCostInfo(costDetails);

            vo.setIsTail(costDetails.getIsTail());// 是否尾款
            vo.setDiscountOption(costDetails.getDiscountType());// 贴息方式

            // 有子产品融资项目
            if (WhetherEnum.No.getIndex().equals(costDetails.getIsSubProduct())) {
                // 融资项目
                List<FinFinancingItems> resultList = new ArrayList<FinFinancingItems>();
                List<FinFinancingItems> itemsList = financingItemsService.getFinancingItemsList(applyNo, carId);
                if (itemsList != null && itemsList.size() > 0) {
                    for (FinFinancingItems financingItems : itemsList) {
                        FinFinancingItems items = new FinFinancingItems();
                        items.setId(financingItems.getId());
                        items.setApplyNo(applyNo);
                        items.setCarId(carId);
                        items.setFinanceItemCode(financingItems.getFinanceItemCode());
                        items.setFinanceItemName(financingItems.getFinanceItemName());
                        items.setFinanceItemAmt(financingItems.getFinanceItemAmt());
                        items.setFinanceItemTotal(financingItems.getFinanceItemTotal());
                        List<FinFinancingItems> sonList = financingItemsService.getApplyFinancingItemsList(applyNo, financingItems.getId());
                        if (sonList != null && sonList.size() > 0) {
                            items.setSonList(sonList);
                        }
                        resultList.add(items);
                    }
                    vo.setItemList(resultList);
                }
            }

            // 贴息明细
            List<FinDiscountDetails> discountList = discountDetailsService.getDiscountDetailsList(applyNo, costDetails.getId(), costDetails.getCostType());
            vo.setDiscountList(discountList);
        }

        return vo;
    }

    /**
     * 获取附加贷产品信息
     *
     * @param applyNo
     * @param carId
     * @param costType
     * @return
     */
    public FinanceInfoBean getAddProductInfo(String applyNo, Long carId, String costType) {

        FinanceInfoBean vo = null;
        // 融资信息
        FinCostDetails costDetails = this.getApplyCostDetails(applyNo, carId, costType);
        if (costDetails != null) {
            vo = new FinanceInfoBean();
            if("equalrental".equals(costDetails.getAlgorithmType())){
                BigDecimal monthlyRate = this.getMonthlyRate(costDetails.getLoanTerm(),costDetails.getMonthPayAmt(),costDetails.getLoanAmt());
                costDetails.setMonthlyRate(monthlyRate);
                BigDecimal myriadCoefficient = this.getMyriadCoefficient(costDetails.getMonthPayAmt(),costDetails.getLoanAmt());
                costDetails.setMyriadCoefficient(myriadCoefficient);
            }
            vo.setCostInfo(costDetails);

            vo.setIsTail(costDetails.getIsTail());// 是否尾款
            vo.setDiscountOption(costDetails.getDiscountType());// 贴息方式

            // 贴息明细
            List<FinDiscountDetails> discountList = discountDetailsService.getDiscountDetailsList(applyNo, costDetails.getId(), costDetails.getCostType());
            vo.setDiscountList(discountList);

            // 融资项目
            List<FinFinancingItems> itemsList = financingItemsService.getFinancingItemsList(applyNo, carId);
            List<FinFinancingItems> resultList = new ArrayList<FinFinancingItems>();
            for (FinFinancingItems financingItems : itemsList) {
                FinFinancingItems items = new FinFinancingItems();
                items.setId(financingItems.getId());
                items.setApplyNo(applyNo);
                items.setCarId(carId);
                items.setFinanceItemCode(financingItems.getFinanceItemCode());
                items.setFinanceItemName(financingItems.getFinanceItemName());
                items.setFinanceItemAmt(financingItems.getFinanceItemAmt());
                items.setFinanceItemTotal(financingItems.getFinanceItemTotal());
                List<FinFinancingItems> sonList = financingItemsService.getApplyFinancingItemsList(applyNo, financingItems.getId());
                if (sonList != null && sonList.size() > 0) {
                    items.setSonList(sonList);
                }
                resultList.add(items);
            }
            vo.setItemList(resultList);
        }

        return vo;
    }

    /**
     * 保存融资列表信息
     *
     * @param applyNo
     * @param inList
     * @return
     */
    public List<FinCostDetails> saveCostDetailsList(String applyNo, Long carId, List<CalculatorDTO> inList) {

        List<FinCostDetails> resultList = new ArrayList<FinCostDetails>();
        for (CalculatorDTO condition : inList) {
            condition.setCarId(carId);
            FinCostDetails costDetails = this.saveOrUpdateCostDetails(applyNo, condition);
            resultList.add(costDetails);
            // 融资项目
            List<FinFinancingItems> itemsList = condition.getItemsList();
            if (itemsList != null && itemsList.size() > 0) {
                if (carId != null) {
                    financingItemsService.saveApplyFinancingItemsList(applyNo, carId, itemsList);
                } else {
                    financingItemsService.saveApplyFinancingItemsList(applyNo, null, itemsList);
                }
            }
            // 贴息项目
            List<FinDiscountDetails> discountList = condition.getDiscountList();
            if (discountList != null && discountList.size() > 0) {
                discountDetailsService.saveApplyDiscountDetailsList(applyNo, costDetails.getId(), costDetails.getCostType(), condition.getDiscountType(), condition.getDiscountAmt(), discountList);
            }
            // 任意贷
            if ("arbitraryloan".equals(condition.getAlgorithmType())) {
                Assert.isTrue(condition.getRentList()!=null && condition.getRentList().size()>0,"任意贷产品必须调整租金才能保存");
                rentAdjustDetailsService.saveRentAdjustDetails(applyNo, condition.getRentList());
            }
        }
        return resultList;
    }

    /**
     * 更新融资列表信息
     *
     * @param applyNo
     * @param inList
     */
    public List<FinCostDetails> updateCostDetailsList(String applyNo, Long carId, List<CalculatorDTO> inList) {

        List<FinCostDetails> resultList = new ArrayList<FinCostDetails>();
        FinCostDetails addDetails = this.getApplyCostDetails(applyNo, CostType.AFFIXAMT.getIndex());
        // 删除附加贷信息
        if (inList.size() == 1 && addDetails != null) {
            // 删除
            this.removeById(addDetails.getId());
            // 融资项目删除
            List<FinFinancingItems> itemsDeleteList = financingItemsService.getApplyFinancingItemsList(applyNo);
            if (itemsDeleteList != null && itemsDeleteList.size() > 0) {
                for (FinFinancingItems financingItems : itemsDeleteList) {
                    financingItemsService.removeById(financingItems.getId());
                }
            }
            // 贴息项目删除
            List<FinDiscountDetails> disDeleteList = discountDetailsService.getDiscountDetailsList(applyNo, addDetails.getId(),CostType.AFFIXAMT.getIndex());
            if (disDeleteList != null && disDeleteList.size() > 0) {
                for (FinDiscountDetails discountDetails : disDeleteList) {
                    discountDetailsService.removeById(discountDetails.getId());
                }
            }
        }

        // 更新或保存融资列表
        for (CalculatorDTO condition : inList) {
            // 融资费用信息
            FinCostDetails costDetails = this.getById(condition.getId());
            condition.setCarId(carId);
            if (costDetails != null) {
                this.upateApplyCostDetails(costDetails, condition);
            } else {
                costDetails = this.saveOrUpdateCostDetails(applyNo, condition);
            }
            resultList.add(costDetails);
            // 融资项目，先删除再新增
            List<FinFinancingItems> itemsDeleteList = financingItemsService.getApplyFinancingItemsList(applyNo);
            if (itemsDeleteList != null && itemsDeleteList.size() > 0) {
                for (FinFinancingItems financingItems : itemsDeleteList) {
                    financingItemsService.removeById(financingItems.getId());
                }
            }
            List<FinFinancingItems> itemsList = condition.getItemsList();
            if (itemsList != null && itemsList.size() > 0) {
                if (carId != null) {
                    financingItemsService.saveApplyFinancingItemsList(applyNo, carId, itemsList);
                } else {
                    financingItemsService.saveApplyFinancingItemsList(applyNo, null, itemsList);
                }
            }
            // 贴息项目，先删除再新增
            List<FinDiscountDetails> disDeleteList = discountDetailsService.getDiscountDetailsList(applyNo, costDetails.getId(),costDetails.getCostType());
            if (disDeleteList != null && disDeleteList.size() > 0) {
                for (FinDiscountDetails discountDetails : disDeleteList) {
                    discountDetailsService.removeById(discountDetails.getId());
                }
            }
            List<FinDiscountDetails> discountList = condition.getDiscountList();
            if (discountList != null && inList.size() > 0) {
                discountDetailsService.saveApplyDiscountDetailsList(applyNo, costDetails.getId(), costDetails.getCostType(), condition.getDiscountType(), condition.getDiscountAmt(), discountList);
            }
            // 任意贷
            if ("arbitraryloan".equals(condition.getAlgorithmType())) {
                Assert.isTrue(condition.getRentList()!=null && condition.getRentList().size()>0,"任意贷产品必须调整租金才能保存");
                rentAdjustDetailsService.saveRentAdjustDetails(applyNo, condition.getRentList());
            }
        }
        return resultList;
    }

    /**
     * 修改车价专用
     * @param applyNo
     * @param carId
     * @param inList
     * @return
     */
    public List<FinCostDetails> updateCostDetailsForSalePrice(String applyNo, Long carId, List<CalculatorDTO> inList){

        List<FinCostDetails> resultList = new ArrayList<FinCostDetails>();
        // 更新或保存融资列表
        for (CalculatorDTO condition : inList) {
            // 融资费用信息
            FinCostDetails costDetails = this.getById(condition.getId());
            condition.setCarId(carId);
            if (costDetails != null) {
                this.upateApplyCostDetails(costDetails, condition);
            } else {
                costDetails = this.saveOrUpdateCostDetails(applyNo, condition);
            }
            resultList.add(costDetails);

            // 贴息项目，先删除再新增
            List<FinDiscountDetails> disDeleteList = discountDetailsService.getDiscountDetailsList(applyNo, costDetails.getId());
            if (disDeleteList != null && disDeleteList.size() > 0) {
                for (FinDiscountDetails discountDetails : disDeleteList) {
                    discountDetailsService.removeById(discountDetails.getId());
                }
            }
            List<FinDiscountDetails> discountList = condition.getDiscountList();
            if (discountList != null && inList.size() > 0) {
                discountDetailsService.saveApplyDiscountDetailsList(applyNo, costDetails.getId(), costDetails.getCostType(), condition.getDiscountType(), condition.getDiscountAmt(), discountList);
            }
        }
        return resultList;

    }

    @Override
    public List<FinCostDetails>  getAllMoney(ApplyTotalCondition applyTotalCondition) {
        List<FinCostDetails>  finCostDetailsList=this.baseMapper.getAllMoney(applyTotalCondition);
        return finCostDetailsList;
    }
}
